package top.dyzmj.detty.core.buffer;

import top.dyzmj.detty.core.utils.StringUtil;
import top.dyzmj.detty.core.utils.internal.PlatformDependent;

/**
 * 描述: 缓冲区分配器的骨架实现
 *
 * @author dongYu
 * @date 2021/11/16
 */
public abstract class AbstractByteBufAllocator implements ByteBufAllocator {

	/**
	 * 默认初始化容量
	 */
	static final int DEFAULT_INITIAL_CAPACITY = 256;
	/**
	 * 默认最大容量
	 */
	static final int DEFAULT_MAX_CAPACITY = Integer.MAX_VALUE;
	/**
	 * 计算阈值
	 */
	static final int CALCULATE_THRESHOLD = 1048576 * 4; // 4 MiB page

	/**
	 * 是否默认使用堆外内存
	 */
	private final boolean directByDefault;
	/**
	 * 定义一个空的缓冲区
	 */
	private final ByteBuf emptyBuf;

	protected AbstractByteBufAllocator(boolean preferDirect) {
		directByDefault = preferDirect && PlatformDependent.hasUnsafe();
		emptyBuf = new EmptyByteBuf(this);
	}

	/**
	 * 验证初始化大小是否超出最大
	 */
	private static void validate(int initialCapacity, int maxCapacity) {
		if (initialCapacity < 0) {
			throw new IllegalArgumentException("initialCapacity: " + initialCapacity + " (expectd: 0+)");
		}
		if (initialCapacity > maxCapacity) {
			throw new IllegalArgumentException(String.format("initialCapacity: %d (expected: not greater than maxCapacity(%d)", initialCapacity, maxCapacity));
		}
	}

	@Override
	public ByteBuf buffer() {
		if (directByDefault) {
			return directBuffer();
		}
		return heapBuffer();
	}

	@Override
	public ByteBuf buffer(int initialCapacity) {
		if (directByDefault) {
			return directBuffer(initialCapacity);
		}
		return heapBuffer(initialCapacity);
	}

	@Override
	public ByteBuf buffer(int initialCapacity, int maxCapacity) {
		if (directByDefault) {
			return directBuffer(initialCapacity, maxCapacity);
		}
		return heapBuffer(initialCapacity, maxCapacity);
	}

	@Override
	public ByteBuf ioBuffer() {
		if (PlatformDependent.hasUnsafe()) {
			return directBuffer(DEFAULT_INITIAL_CAPACITY);
		}
		return heapBuffer(DEFAULT_INITIAL_CAPACITY);
	}

	@Override
	public ByteBuf ioBuffer(int initialCapacity) {
		if (PlatformDependent.hasUnsafe()) {
			return directBuffer(initialCapacity);
		}
		return heapBuffer(initialCapacity);
	}

	@Override
	public ByteBuf ioBuffer(int initialCapacity, int maxCapacity) {
		if (PlatformDependent.hasUnsafe()) {
			return directBuffer(initialCapacity, maxCapacity);
		}
		return heapBuffer(initialCapacity, maxCapacity);
	}

	@Override
	public ByteBuf heapBuffer() {
		return heapBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
	}

	@Override
	public ByteBuf heapBuffer(int initialCapacity) {
		return heapBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
	}

	@Override
	public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {
		if (initialCapacity == 0 && maxCapacity == 0) {
			return emptyBuf;
		}
		validate(initialCapacity, maxCapacity);
		return newHeapBuffer(initialCapacity, maxCapacity);
	}

	@Override
	public ByteBuf directBuffer() {
		return directBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
	}

	@Override
	public ByteBuf directBuffer(int initialCapacity) {
		return directBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
	}

	@Override
	public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
		if (initialCapacity == 0 && maxCapacity == 0) {
			return emptyBuf;
		}
		validate(initialCapacity, maxCapacity);
		return newDirectBuffer(initialCapacity, maxCapacity);
	}

	@Override
	public String toString() {
		return StringUtil.simpleClassName(this) + "(directByDefault: " + directByDefault + ')';
	}

	@Override
	public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
		if (minNewCapacity < 0) {
			throw new IllegalArgumentException("minNewCapacity: " + minNewCapacity + " (expectd: 0+)");
		}
		if (minNewCapacity > maxCapacity) {
			throw new IllegalArgumentException(String.format("minNewCapacity: %d (expected: not greater than maxCapacity(%d)", minNewCapacity, maxCapacity));
		}

		// 4 MiB page
		final int threshold = CALCULATE_THRESHOLD;

		if (minNewCapacity == threshold) {
			return threshold;
		}
		// 如果超过阈值，不要翻倍，而只是增加阈值。
		if (minNewCapacity > threshold){
			int newCapacity = minNewCapacity / threshold * threshold;
			if (newCapacity > maxCapacity - threshold) {
				newCapacity = maxCapacity;
			} else {
				newCapacity += threshold;
			}
			return newCapacity;
		}

		// 64 <= newCapacity is a power of 2 <= threshold
		// 不超过阈值, 从64开始，增加到4个MiB。
		int newCapacity = 64;
		while (newCapacity < minNewCapacity){
			newCapacity <<= 1;
		}
		return Math.min(newCapacity, maxCapacity);
	}

	/**
	 * 用给定的 initialCapacity 和 maxCapacity 创建一个堆 {@link ByteBuf} 缓冲区。
	 */
	protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);

	/**
	 * 用给定的 initialCapacity 和 maxCapacity 创建一个直接的 {@link ByteBuf} 缓冲区。
	 */
	protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);
}
